package org.geppeto.eva.synchronizer;

import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.lang.Thread;

import org.geppeto.eva.synchronizer.Token.MyTimerTask;

public class Event extends Mechanism {

	public abstract class MyTimerTask extends TimerTask {
		protected InstanceManager _theMngr;
		protected String _theKey;
		protected String _user;
		public MyTimerTask(InstanceManager mngr, String key){
			super();
			_theMngr = mngr;
			_theKey = key;
		}
		public MyTimerTask(InstanceManager mngr, String key, String user){
			super();
			_theMngr = mngr;
			_theKey = key;
			_user = user;
		}
	}
	
	private InstanceManager _inst;
	private String _key;
	Date _registrationEndTime;
	private int _minParticipants;
	private int _maxParticipants;
	private ArrayList<String> listOfParticipants = new ArrayList<String>();
	private ArrayList<Timer> userAlerts = new ArrayList<Timer>();
	private MyTimerTask _onRegistrationEndTask;

	Timer _timer = new Timer();
	
	public Event(InstanceManager inst, String key, int time, int minParticipants, int maxParticipants){
		_inst = inst;
		_key = key;

		// set event time (seconds)
		Date now = new Date();
		_registrationEndTime = new Date( now.getTime() + time * 1000);
		
		// set event participants
		_minParticipants = minParticipants;
		_maxParticipants = maxParticipants;
		
		// schedule action on event start 
		_onRegistrationEndTask = new MyTimerTask(_inst, _key) {
			@Override
			public void run() {
				try{			
					_theMngr.sendEventStatus(_theKey);
				}
				catch (Exception ex){}
			}
		};
		
		Timer eventStartTimer = new Timer();
		eventStartTimer.schedule(_onRegistrationEndTask, _registrationEndTime);
		userAlerts.add(eventStartTimer);
	}

	public void setMinParticipants(int minParticipants){
		_minParticipants = minParticipants;
	}

	public void setMaxParticipants(int maxParticipants){
		_maxParticipants = maxParticipants;
	}
	
	protected Boolean userRegister(String userID){
		if(listOfParticipants.indexOf(userID) != -1){
			return true;
		}
		if(listOfParticipants.size() >= _maxParticipants){
			return false;
		}
		listOfParticipants.add(userID);
		return true;
	}
	
	protected Boolean userUnregister(String userID){
		if(listOfParticipants.indexOf(userID) == -1){
			return true;
		}
		listOfParticipants.remove(listOfParticipants.indexOf(userID));
		return true;
	}	

	protected String getInfo(){
		try{
			Format formatter;
			formatter = new SimpleDateFormat("dd.MM.yy hh:mm:ss");
			String date = formatter.format(_registrationEndTime);

			String result="";
			result = "{description: 'getInfo', "
				+ "minParticipants: " + Integer.toString(_minParticipants) + ", "
				+ "maxParticipants: " + Integer.toString(_maxParticipants) + ", "
				+ "eventTime: '" +  date + "', "
				+ "usersCount: " + Integer.toString(listOfParticipants.size())
				+ "}";
			return result;
		} catch (Exception ex){
			return "Failed to get info.";
		}
	}
	
	protected Map<String, Object> getInfoObject(){
		try{
			Format formatter;
			formatter = new SimpleDateFormat("dd.MM.yy hh:mm:ss");
			String date = formatter.format(_registrationEndTime);

			Map<String, Object> result = new HashMap<String, Object>();
			result.put("description", "getInfo");
			result.put("minParticipants", Integer.toString(_minParticipants));
			result.put("maxParticipants", Integer.toString(_maxParticipants));
			result.put("eventTime", date);
			result.put("usersCount", Integer.toString(listOfParticipants.size()));
			return result;
		} catch (Exception ex){
			Map<String, Object> result = new HashMap<String, Object>();
			result.put("error", "Failed to get info.");
			return result;
		}
	}
	
	protected Map<String, Object> getEventStatus(){
		try{
			_timer.cancel();
			
			int participants = listOfParticipants.size();
			String eventStatus = "";
			if(_minParticipants <= participants){
				eventStatus = "true";
			} else {
				eventStatus = "false";
			}
			
			Map<String, Object> result = new HashMap<String, Object>();
			result.put("description", "eventStart");
			result.put("eventStarting", eventStatus);
			return result;
		} catch (Exception ex){
			Map<String, Object> result = new HashMap<String, Object>();
			result.put("error", "Failed to get status.");
			return result;
		}
	}	

	protected Boolean addAlert(String user, int time){
		try{
			MyTimerTask newAlertTask = new MyTimerTask(_inst, _key, user) {
				@Override
				public void run() {
					try{			
						_theMngr.alertUser(_theKey, _user);
					}
					catch (Exception ex){}
				}
			};	

			// set alert time
			Date alertTime = new Date( _registrationEndTime.getTime() - time * 1000);
			
			// schedule alert
			Timer userAlertTimer = new Timer();
			userAlertTimer.schedule(newAlertTask, alertTime);
			userAlerts.add(userAlertTimer);
			
			// return confirmation to user
			Format formatter;
			formatter = new SimpleDateFormat("dd.MM.yy hh:mm:ss");
			String srtAlertTime = formatter.format(alertTime);

			return true;
		} catch (Exception ex){
			return false;
		}
	}	

	protected static Map<String, Object> userAlert(String user){
		try{
			Map<String, Object> result = new HashMap<String, Object>();
			result.put("description", "alertUser");
			result.put("user", user);
			return result;
		} catch (Exception ex){
			Map<String, Object> result = new HashMap<String, Object>();
			result.put("error", "Failed to get status.");
			return result;
		}
	}

}
